#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug> //调试输出
#include <QMessageBox> //消息框
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , serial(new QSerialPort(this)) //创建串口对象
{
    ui->setupUi(this);

    //设置窗口标题
    setWindowTitle("PWM LED控制器");
    // 初始化滑块范围 (0-1000)
    ui->slider->setRange(0,1000);
    ui->slider->setValue(300); //初始值
    ui->valueLabel->setText("300"); //显示当前值

    // 初始化串口列表
    initSerialPorts();

    // 调用初始化图表的函数
    initchart();

    //滑块移动时触发
    connect(ui->slider,&QSlider::sliderMoved,this,&MainWindow::onSilderMoved);
    // 连接按钮点击时触发
    connect(ui->connectButton,&QPushButton::clicked,this,&MainWindow::onConnectClicked);
    // 串口错误发生时触发
    connect(serial,&QSerialPort::errorOccurred,this,&MainWindow::handleSerialError);
}

MainWindow::~MainWindow()
{
    delete ui;
}

// 初始化可用串口列表
void MainWindow::initSerialPorts()
{
    ui->portComboBox->clear(); //清空下拉框
    // 获取所有可用串口
    const auto infos = QSerialPortInfo::availablePorts();
    for(const QSerialPortInfo &info : infos){
        ui->portComboBox->addItem(info.portName()); //添加到下拉框
    }

}
// 初始化图表的函数
void MainWindow::initchart()
{
    // 创建图表对象
    chart = new QChart();
    // 设置图表标题为"UART 时序图"
    chart->setTitle("UART 时序图");
    // 设置图表主题为深色主题
    chart->setTheme(QChart::ChartThemeDark);

    // 创建折线序列对象（用于存储和显示数据点）
    series = new QLineSeries();
    // 设置序列名称为"PWM值"
    series->setName("PWM值");
    // 设置折线颜色为青蓝色（RGB:0,200,255）
    series->setColor(QColor(0,200,255));

    // 将折线序列添加到图表中
    chart->addSeries(series);

    // 创建X轴对象（用于表示数据点序号）
    axisX = new QValueAxis();
    // 设置X轴标题为"数据点"
    axisX->setTitleText("数据点");
    // 设置X轴初始显示范围为0到100
    axisX->setRange(0,100);
    // 设置X轴标签格式为整数
    axisX->setLabelFormat("%d");

    // 创建Y轴对象（用于表示PWM值）
    axisY = new QValueAxis();
    // 设置Y轴标题为"PWM值"
    axisY->setTitleText("PWM值");
    // 设置Y轴范围为0到1000（与滑块范围一致）
    axisY->setRange(0,1000);
    // 设置Y轴标签格式为整数
    axisY->setLabelFormat("%d");

    // 将X轴添加到图表底部
    chart->addAxis(axisX,Qt::AlignBottom);
    // 将Y轴添加到图表左侧
    chart->addAxis(axisY,Qt::AlignLeft);

    // 将折线序列与X轴关联
    series->attachAxis(axisX);
    // 将折线序列与Y轴关联
    series->attachAxis(axisY);

    // 创建图表视图对象（用于显示图表）
    QChartView *chartView = new QChartView(chart);
    // 设置图表视图启用抗锯齿渲染（使线条更平滑）
    chartView->setRenderHint(QPainter::Antialiasing);

    // 将图表视图添加到界面的图表布局中
    ui->chartLayout->addWidget(chartView);

    // 启动计时器（用于控制图表数据点的添加频率）
    timer.start();
}

// 滑块移动处理函数
void MainWindow::onSilderMoved(int position)
{
    // 更新显示值
    ui->valueLabel->setText(QString::number(position));
    // 如果串口已打开，发送数据
    if(serial->isOpen()){
        // 将数值转换为字符串并添加结束符\r\n
        QString data = QString::number(position)+"\r\n";
        //发送数据包
        serial->write(data.toUtf8());

        // 当计时器记录的时间超过100毫秒时（控制数据点添加频率）
        if(timer.elapsed() > 100){
            // 向折线序列添加一个数据点（x:数据点计数，y:滑块位置）
            series->append(dataCount++,position);

            // 当数据点数量超过100时，调整X轴范围实现自动滚动
            if(dataCount > 100){
                axisX->setRange(dataCount - 100,dataCount);
            }

            // 重置计时器，重新计时
            timer.start();
        }
    }
}
// 连接按钮点击处理函数
void MainWindow::onConnectClicked()
{
    if(serial->isOpen()){// 如果已连接
       serial->close();// 关闭串口
       ui->connectButton->setText("连接串口");// 更新按钮文本
       ui->statusLabel->setText("已断开");// 更新状态
    }else{// 如果未连接
       QString portName = ui->portComboBox->currentText();// 获取选择的串口
       // 配置串口参数
       serial->setPortName(portName);// 设置端口名
       serial->setBaudRate(QSerialPort::Baud115200);// 波特率115200
       serial->setDataBits(QSerialPort::Data8);// 8位数据位
       serial->setParity(QSerialPort::NoParity);// 无校验位
       serial->setStopBits(QSerialPort::OneStop);// 1位停止位

       //打开串口
       if(serial->open(QIODevice::ReadWrite)){
           ui->connectButton->setText("断开连接");// 更新按钮文本
           ui->statusLabel->setText("已连接："+portName);// 更新状态

           // 清空折线序列中的数据
           series->clear();
           dataCount = 0; // 重置数据点计数器
           axisX->setRange(0,100); // 重置X轴范围
       }else{
           // 打开失败显示错误
           QMessageBox::critical(this,"错误","无法打开串口："+serial->errorString());
       }
    }
}
// 串口错误处理函数
void MainWindow::handleSerialError(QSerialPort::SerialPortError error)
{
    if(error == QSerialPort::ResourceError){// 资源错误（如拔出设备）
        QMessageBox::critical(this,"错误","串口错误："+serial->errorString());
        if(serial->isOpen()){
            serial->close();// 关闭串口
        }
        ui->connectButton->setText("连接串口");// 重置按钮文本
        ui->statusLabel->setText("连接错误");// 更新状态
    }
}


